package com.zbf.task.taskweb;

import com.zbf.task.core.utils.UID;
import com.zbf.task.dao.TaskDao;
import com.zbf.task.job.TestJob;
import com.zbf.utils.MyDateTimeUtils;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;

/**
 * 作者: LCG
 * 日期: 2019/8/16 09:09
 * 描述: 定时任务的管理（动态的新增删除任务）
 */
@RestController
public class TaskMangerController {

    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;

    @Autowired
    private TaskDao taskDao;

    //动态的添加一个定时任务，这个定时任务信息是保存在内存中的
    @RequestMapping("taskAdd")
    public Object tastAddTask() throws SchedulerException {

        Scheduler defaultScheduler = StdSchedulerFactory.getDefaultScheduler();
        defaultScheduler.start();
        JobDetail jobDetail=JobBuilder.newJob(HelloJob.class)
                .withIdentity("myJobName","myJobGroup")
                .withIdentity(new JobKey("AD1"))
                .build();
        Trigger trigger=TriggerBuilder
                .newTrigger()
                .withIdentity("triggerName","triggerGroup")
                .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?"))
                .startAt(new Date(new Date().getTime()+10000))
                .endAt(new Date(new Date().getTime()+100000))
                .build();
        defaultScheduler.scheduleJob(jobDetail,trigger);

        return null;
    }

    /**
     * 创建一个持久化的定时任务,这个定时任务的信息会保存在数据库中
     * 注意这里通过JobBuilder.newJob(TestJob.class)创建新的Job这时
     * 候如果TestJob需要的一些依赖注入的话，会报空指针异常，因为这
     * 里是通过TestJob.class反射生成的TestJob实例
     * @return
     * @throws SchedulerException
     */
    @RequestMapping("addTask")
    public Object addTask(@RequestBody Map<String,Object> map) throws SchedulerException {
        //获取调度
        Scheduler scheduler = schedulerFactoryBean.getScheduler();

        //创建一个Job map.get("groupJobKey").toString()就是JOB的name 并且不可重复
        // map.get("groupJobName").toString()是JOB的分组
        JobDataMap jobDataMap=new JobDataMap();
        jobDataMap.put("canshu1","123456");

        JobDetail jobDetail = JobBuilder.newJob(TestJob.class)
                //.withIdentity(map.get("groupJobKey").toString(), map.get("groupJobName").toString())
                .withIdentity(new JobKey("JOBNAME-"+UID.getUUID16())) //对应的就是JOb的Name ，这两个方法同时用的话后边的覆盖前边的
                .setJobData(jobDataMap) //该方法可以设置JOb的信息（在这里可以添加你的参数数）
                .withDescription(map.get("description").toString())//任务的描述
                .build();

        //创建定时器
        TriggerBuilder<CronTrigger> cronTrigger = TriggerBuilder.newTrigger()
                .withIdentity(map.get("groupTriggerKey").toString(), map.get("groupTriggerName").toString())
                .withSchedule(CronScheduleBuilder.cronSchedule(map.get("cron").toString()));//设置定时的表达式

        //设置任务的开始时间
        if(map.get("startTime")!=null){//查看是否有指定任务的开始时间
            Date startTime = MyDateTimeUtils.fromStringToDate(map.get("startTime").toString());
            cronTrigger.startAt(startTime);
        }
        //设置任务的结束时间(将StartTIme和EndTime设置一致那么任务就只会被执行一次)
        if(map.get("endTime")!=null){
            Date endTime = MyDateTimeUtils.fromStringToDate(map.get("endTime").toString());
            cronTrigger.endAt(endTime);
        }
        //创建调度
        CronTrigger build = cronTrigger.build();
        //将任务Job和定时器加入调度
        scheduler.scheduleJob(jobDetail, build);
        //开始启动任务
        scheduler.start();

        return null;
    }

    /**
     * 获取任务的列表
     * @return
     */
    @RequestMapping("getListTask")
    public List<Map<String,Object>> getListTask(){



        return null;
    }


    /**
     * 动态的暂停一个定时任务,注意暂停以后是可以重新启动的
     * @param map
     * @throws SchedulerException
     */
    @RequestMapping("zanTing")
    public void toZanTingJob(@RequestBody Map<String,String> map) throws SchedulerException {

        Scheduler scheduler = schedulerFactoryBean.getScheduler();

        scheduler.pauseJob(new JobKey(map.get("jobKey")));

    }

    /**
     *  恢复暂停的定时任务
     * @param map
     * @return
     */
    @RequestMapping("toHuiFu")
    public Object toHuiFu(@RequestBody Map<String,String> map) throws SchedulerException {

        if(map.get("jobKey")!=null){
            //先更新一下开始的时间
            map.put("jobName",map.get("jobKey"));
            map.put("next_time",""+(System.currentTimeMillis()+5000));

            /*Map<String, Object> triggerInfo = taskDao.getTriggerInfo(map);
            if(triggerInfo!=null){
              map.put("triggerName",triggerInfo.get("TRIGGER_NAME").toString());
              map.put("triggerGroupName",triggerInfo.get("TRIGGER_GROUP").toString());
              Long prev_fire_time =Long.valueOf(triggerInfo.get("PREV_FIRE_TIME").toString());
            }*/

            taskDao.updateTriggerNextStartTime(map);
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            scheduler.resumeJob(new JobKey(map.get("jobKey")));

        }else{

        }

        return null;
    }

    /**
     * 动态的停止一个定时任务，scheduler被停止后，
     * 除非重新实例化，否则不能重新启动；
     * 只有当scheduler启动后，即使处于暂停状态也不行，
     * trigger才会被触发（job才会被执行）。不要随便的使用
     * @return
     */
    @RequestMapping("toTingZhiJob")
    public Object toTingZhiJob() throws SchedulerException {

        Scheduler scheduler = schedulerFactoryBean.getScheduler();

        scheduler.shutdown();

        return null;
    }


    /**
     * 动态的删除一个或者多个任务
     * 这是将定时任务直接的暴力的删除掉，这个操作之后定时任务将不再执行
     * @return
     */
    @RequestMapping("toDeleteAnJob")
    public Object toDeleteAnJob(@RequestBody List<String> jobkeys) throws SchedulerException {

        if(jobkeys.size()>0){
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            List<JobKey> list=new ArrayList<>();
            jobkeys.forEach((key)->{
                list.add(new JobKey(key));
            });
            scheduler.deleteJobs(list);
        }
        return null;
    }


    /**
     *  动态的去更新一个定时任务，主要是修改任务的执行表达式
     * @return
     */
    @RequestMapping("toUpdateAnJobCron")
    public Object toUpdateAnJob(@RequestBody Map<String,String> map) throws SchedulerException {

        //更新任务的执行表达式
        if(map.get("jobKey")!=null){
            map.put("jobName",map.get("jobKey"));
            Map<String, Object> triggerInfo = taskDao.getTriggerInfo(map);
            if(triggerInfo!=null){
                Scheduler scheduler = schedulerFactoryBean.getScheduler();
                CronTrigger cronTrigger = TriggerBuilder.newTrigger()
                        .withSchedule(CronScheduleBuilder.cronSchedule(map.get("cron"))).build();//设置定时的表达式
                scheduler.rescheduleJob(new TriggerKey(triggerInfo.get("TRIGGER_NAME").toString(),triggerInfo.get("TRIGGER_GROUP").toString()),cronTrigger);
            }
        }


        return null;
    }

}
